{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Extracting MNIST_data\\train-images-idx3-ubyte.gz\n",
      "Extracting MNIST_data\\train-labels-idx1-ubyte.gz\n",
      "Extracting MNIST_data\\t10k-images-idx3-ubyte.gz\n",
      "Extracting MNIST_data\\t10k-labels-idx1-ubyte.gz\n"
     ]
    }
   ],
   "source": [
    "# 利用tensorboard中的image功能将训练的数据集和训练效果可视化\n",
    "# 数据集介绍\n",
    "# MNIST数据集，100k的训练数据，10k的预测数据，数据由tensorflow中的examples.tutorials.mnist读取 \n",
    "# 数据集介绍：：Yann LeCun's website\n",
    "# 由28*28的像素组成输入特征，输出特征为0-9的数字\n",
    "\n",
    "# 可调节参数：\n",
    "# --------\n",
    "# batch_size, initial_weight,二次损失函数,learning_rate,epoch_n\n",
    "# --------\n",
    "\n",
    "import tensorflow as tf\n",
    "from tensorflow.examples.tutorials.mnist import input_data\n",
    "from tensorflow.contrib.tensorboard.plugins import projector\n",
    "\n",
    "mnist = input_data.read_data_sets(\"MNIST_data\", one_hot = True)\n",
    "\n",
    "#定义会话\n",
    "sess = tf.Session()\n",
    "\n",
    "max_steps = 1001\n",
    "image_num = 3000\n",
    "DIR = \"D://tensorboardLogDir/\" # projector所在的父目录\n",
    "\n",
    "embedding = tf.Variable(tf.stack(mnist.test.images[: image_num]), trainable = False, name = \"embedding\")\n",
    "\n",
    "# mini_batch的大小\n",
    "batch_size = 100\n",
    "batch_n = mnist.train.num_examples // batch_size\n",
    "\n",
    "# 创建一个命名空间\n",
    "with tf.name_scope(\"input\"):\n",
    "    # # 定义两个placeholder用来feed数据，分别代表x和y --784列和10列(one-hot)\n",
    "    x = tf.placeholder(tf.float32, [None, 784], name = \"x_input\") # 一张图片1行\n",
    "    y = tf.placeholder(tf.float32, [None, 10], name = \"y_input\")\n",
    "\n",
    "with tf.name_scope(\"input-reshape\"):\n",
    "    image_x_reshape = tf.reshape(x, [-1, 28, 28, 1]) # -1表示不确定， 1为黑白图片的维度，彩色则为3\n",
    "    tf.summary.image(\"input\", image_x_reshape, 10) # 在summary中放入10张图片\n",
    "# tensorflow中定义一个函数，summary变量的所有特点    \n",
    "def variables_summary(variable):\n",
    "    with tf.name_scope(\"summary\"):\n",
    "        # 通过summary.scalar建立对标量的追踪\n",
    "        mean = tf.reduce_mean(variable)\n",
    "        tf.summary.scalar(\"mean\", mean)\n",
    "        stddev = tf.sqrt(tf.reduce_mean(tf.square(variable - mean)))\n",
    "        tf.summary.scalar(\"stddev\", stddev)\n",
    "        tf.summary.histogram(\"histogram\", variable)\n",
    "\n",
    "# # ----\n",
    "# # 构建多分类回归\n",
    "# # 定义weight和bias，初始化分别为正态随机和0.0\n",
    "with tf.name_scope(\"lager\"):\n",
    "    with tf.name_scope(\"weight\"):\n",
    "        initial_weight = tf.random_normal([784, 10])\n",
    "        weight = tf.Variable(initial_weight)\n",
    "        variables_summary(weight) # 利用summary函数观察一下weight的变化情况\n",
    "    with tf.name_scope(\"bias\"):\n",
    "        bias = tf.Variable(tf.zeros([10]))\n",
    "        variables_summary(bias) # 利用summary观察一下bias的变化情况\n",
    "    with tf.name_scope(\"mat_and_plus\"):\n",
    "        a = tf.matmul(x, weight) + bias\n",
    "    with tf.name_scope(\"softmax\"):\n",
    "        y_head = tf.nn.softmax(a)\n",
    "\n",
    "# # 定义二次损失函数并依据梯度下降法进行训练 -- 这样梯度下降的train就变成了x和y的函数\n",
    "with tf.name_scope(\"loss\"):\n",
    "    learning_rate = 0.1\n",
    "    loss = tf.reduce_mean(tf.square(y - y_head))\n",
    "    tf.summary.scalar(\"loss\", loss) # 利用summary观察一下loss的变化\n",
    "    optimizer = tf.train.GradientDescentOptimizer(learning_rate)\n",
    "    train = optimizer.minimize(loss)\n",
    "\n",
    "init = tf.global_variables_initializer()\n",
    "\n",
    "with tf.name_scope(\"accuracy\"):\n",
    "    correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_head, 1)) # tf.argmax找到x中等于1的最大的id\n",
    "    correction = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) # tf.cast 转换类型，将bool转为float，从而求得准确率\n",
    "    tf.summary.scalar(\"accuracy\", correction)\n",
    "    \n",
    "# 生成metadata文件\n",
    "if tf.gfile.Exists(DIR + \"projector/projector/metadata.tsv\"):\n",
    "    tf.gfile.DeleteRecursively(DIR + \"projector/projector/metadata.tsv\")\n",
    "with open(DIR + \"projector/projector/metadata.tsv\", \"w\") as file:\n",
    "    # 拿到image_num张图片的label并写入metadata\n",
    "    lbs = sess.run(tf.argmax(mnist.test.labels[:], 1))\n",
    "    for i in range(image_num):\n",
    "        file.write(str(lbs[i]) + \"\\n\")\n",
    "        \n",
    "# 将summary的scalar merge\n",
    "merged = tf.summary.merge_all()\n",
    "\n",
    "projector_writer = tf.summary.FileWriter(DIR + 'projector/projector', sess.graph) # 创建FileWriter\n",
    "saver = tf.train.Saver()\n",
    "config = projector.ProjectorConfig()\n",
    "embed = config.embeddings.add()\n",
    "embed.tensor_name = embedding.name\n",
    "embed.metadata_path = DIR + 'projector/projector/metadata.tsv'\n",
    "embed.sprite.image_path = DIR + 'projector/data/mnist_10k_sprite.png'\n",
    "embed.sprite.single_image_dim.extend([28,28])\n",
    "projector.visualize_embeddings(projector_writer,config)\n",
    "\n",
    "for i in range(max_steps):    \n",
    "    batch_xs,batch_ys = mnist.train.next_batch(100)    \n",
    "    run_options = tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE)    \n",
    "    run_metadata = tf.RunMetadata()    \n",
    "    summary,_ = sess.run([merged,train_step],feed_dict={x:batch_xs,y:batch_ys},options=run_options,run_metadata=run_metadata)\n",
    "    projector_writer.add_run_metadata(run_metadata, 'step%03d' % i)\n",
    "    projector_writer.add_summary(summary, i)\n",
    "    print(\"第\" + str(i) + \"次运行\")\n",
    "    if i%100 == 0:      \n",
    "        acc = sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels})\n",
    "        print (\"Iter \" + str(i) + \", Testing Accuracy= \" + str(acc))\n",
    "\n",
    "saver.save(sess, DIR + 'projector/projector/a_model.ckpt', global_step = max_steps)\n",
    "projector_writer.close()\n",
    "sess.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
